﻿using System;
using System.Configuration;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;

namespace JTLeigh.Commerce.Spencer.Core.Common.Services
{

    /// <summary>
    /// An <see cref="IConfigurationService"/> implementation that uses <see cref="ConfigurationManager"/>
    /// to retrieve configuration.
    /// </summary>
    /// <remarks>
    /// <para>
    /// The configuration service can't depend on other services, as these services will directly 
    /// or indirectly depend on the configuration service.
    /// </para>
    /// </remarks>
    public class ConfigurationService : IConfigurationService
    {

        #region IConfigurationService Members

        /// <summary>
        /// Retrieves the specified configuration section.
        /// </summary>
        /// <typeparam name="TSection">The type of <see cref="ConfigurationSection"/> to 
        /// retrieve.</typeparam>
        /// <param name="tenantId">The tenant identifier <see cref="Guid"/> of the tenant who the 
        /// configuration section is to be retrieved for.</param>
        /// <param name="sectionName">The configuration section name to retrieve.</param>
        /// <returns>The resulting <typeparamref name="TSection"/> object.</returns>
        [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Reviewed.")]
        public TSection GetSection<TSection>(Guid tenantId, string sectionName)
            where TSection : ConfigurationSection
        {
            object sectionObject;
            TSection section;

            Safety.AssertArgumentNotNull("sectionName", sectionName);

            sectionObject = ConfigurationManager.GetSection(sectionName);
            if (sectionObject == null)
            {
                throw new ConfigurationErrorsException(String.Format(CultureInfo.InvariantCulture, "The configuration section '{0}' does not exist.", sectionName));
            }
            section = sectionObject as TSection;
            if (section == null)
            {
                throw new ConfigurationErrorsException(String.Format(CultureInfo.InvariantCulture, "The configuration section '{0}' is of type '{1}' and is not assignable to the expected type '{2}'.", sectionName, sectionObject.GetType().FullName, typeof(TSection).FullName));
            }
            return section;
        }

        #endregion // IConfigurationService Members

    }

}
